package com.example.app.view;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.util.AttributeSet;
import android.view.TextureView;

import com.example.app.activity.MLog;

/**
 * Created by 郭敏 on 2018/3/21 0021.
 */
public abstract class PreviewBaseView extends TextureView {
    private String tag = "PreviewBaseView";
    private int ratioWidth = 0;
    private int ratioHeight = 0;


    public PreviewBaseView(Context context) {
        super(context);

    }

    public PreviewBaseView(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public PreviewBaseView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

    }

    private boolean isSetCallback;

    public void setSurfaceCallback() {
        if (isSetCallback) {
            return;
        }
        isSetCallback = true;
        setSurfaceTextureListener(new SurfaceCallback());
    }


    /**
     * 设置录预览方向
     */
    public void setAspectRatio(int width, int height) {
        if (width < 0 || height < 0) {
            throw new IllegalArgumentException("Size cannot be negative.");
        }
        this.ratioWidth = width;
        this.ratioHeight = height;
        requestLayout();
    }

    /**
     * 设置播放视频时 不合尺寸的视频，区中裁剪，铺满TextureView播放
     *
     * @param videoWidth  视频宽
     * @param videoHeight 视频高
     */
    public void setPayCenterCropFill(int videoWidth, int videoHeight) {
        float sx = (float) getWidth() / (float) videoWidth;
        float sy = (float) getHeight() / (float) videoHeight;
        //
        Matrix matrix = new Matrix();
        float maxScale = Math.max(sx, sy);
        //第1步:把视频区移动到View区,使两者中心点重合.
        matrix.preTranslate((getWidth() - videoWidth) / 2, (getHeight() - videoHeight) / 2);
        //第2步:因为默认视频是fitXY的形式显示的,所以首先要缩放还原回来.
        matrix.preScale(videoWidth / (float) getWidth(), videoHeight / (float) getHeight());
        //第3步,等比例放大或缩小,直到视频区的一边超过View一边, 另一边与View的另一边相等. 因为超过的部分超出了View的范围,所以是不会显示的,相当于裁剪了.
        matrix.postScale(maxScale, maxScale, getWidth() / 2, getHeight() / 2);//后两个参数坐标是以整个View的坐标系以参考的
        setTransform(matrix);
        postInvalidate();

    }

    /**
     * 设置播放视频时 不合尺寸的视频，设置在TextureView中心播放
     *
     * @param videoWidth  视频宽
     * @param videoHeight 视频高
     */
    public void setPayTextureViewCenter(int videoWidth, int videoHeight) {
        float sx = (float) getWidth() / (float) videoWidth;
        float sy = (float) getHeight() / (float) videoHeight;
        Matrix matrix = new Matrix();
        //第1步:把视频区移动到View区,使两者中心点重合.
        matrix.preTranslate((getWidth() - videoWidth) / 2, (getHeight() - videoHeight) / 2);
        //第2步:因为默认视频是fitXY的形式显示的,所以首先要缩放还原回来.
        matrix.preScale(videoWidth / (float) getWidth(), videoHeight / (float) getHeight());
        //第3步,等比例放大或缩小,直到视频区的一边和View一边相等.如果另一边和view的一边不相等，则留下空隙
        if (sx >= sy) {
            matrix.postScale(sy, sy, getWidth() / 2, getHeight() / 2);
        } else {
            matrix.postScale(sx, sx, getWidth() / 2, getHeight() / 2);
        }
        setTransform(matrix);
        postInvalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (0 == ratioWidth || 0 == ratioHeight) {
            setMeasuredDimension(width, height);
        } else {
            if (width < height * ratioWidth / ratioHeight) {
                setMeasuredDimension(width, width * ratioHeight / ratioWidth);
            } else {
                setMeasuredDimension(height * ratioWidth / ratioHeight, height);
            }
        }

    }


    protected abstract void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height);

    protected abstract void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height);

    protected abstract boolean onSurfaceTextureDestroyed(SurfaceTexture surface);

    protected abstract void onSurfaceTextureUpdated(SurfaceTexture surface);

    class SurfaceCallback implements SurfaceTextureListener {

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            MLog.e(tag, "预览可用 onSurfaceTextureAvailable width：" + width + " height:" + height);
            //当SurefaceTexture可用的时候，设置相机参数并打开相机
            PreviewBaseView.this.onSurfaceTextureAvailable(surface, width, height);

        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
            MLog.e(tag, "预览大小发生改变 onSurfaceTextureSizeChanged");
            PreviewBaseView.this.onSurfaceTextureSizeChanged(surface, width, height);
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            MLog.e(tag, "预览关闭 onSurfaceTextureDestroyed");
            boolean isDestroyed = PreviewBaseView.this.onSurfaceTextureDestroyed(surface);
            return isDestroyed;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
            // DLog.e(tag, "预览发生更新 onSurfaceTextureDestroyed");
            PreviewBaseView.this.onSurfaceTextureUpdated(surface);
        }
    }
}
